package com.phamloc.fastconnect.scene;

import java.util.ArrayList;

import org.andengine.engine.camera.hud.HUD;
import org.andengine.engine.handler.timer.ITimerCallback;
import org.andengine.engine.handler.timer.TimerHandler;
import org.andengine.entity.modifier.MoveModifier;
import org.andengine.entity.primitive.Line;
import org.andengine.entity.scene.IOnSceneTouchListener;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.SpriteBackground;
import org.andengine.entity.sprite.AnimatedSprite;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.text.Text;
import org.andengine.entity.text.TextOptions;
import org.andengine.extension.physics.box2d.FixedStepPhysicsWorld;
import org.andengine.extension.physics.box2d.PhysicsWorld;
import org.andengine.input.touch.TouchEvent;
import org.andengine.util.adt.align.HorizontalAlign;
import org.andengine.util.adt.color.Color;

import android.graphics.PointF;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.Contact;
import com.badlogic.gdx.physics.box2d.ContactImpulse;
import com.badlogic.gdx.physics.box2d.ContactListener;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.Manifold;
import com.phamloc.fastconnect.GameActivity;
import com.phamloc.fastconnect.base.BaseScene;
import com.phamloc.fastconnect.extras.Pair;
import com.phamloc.fastconnect.manager.SceneManager.SceneType;
import com.phamloc.fastconnect.objects.Shape;

public class GameScene extends BaseScene implements IOnSceneTouchListener {

	private HUD gameHUD;
	private Text scoreText;
	private int score = 0;
	private PhysicsWorld physicsWorld;
	private Text gameOverText;
	private String textScore = "0";
	private Sprite backgroundDraw;
	private ArrayList<Sprite> pointList;
	private PointF currentPoint = null;
	private Sprite smallShape;
	private boolean isDrawComplete = true;
	private boolean isFirst = true;
	private Shape currentShape;
	private Shape drawShape;
	private Sprite circle;
	private Sprite circleInside;
	private int goc = 0;
	private Sprite timer;
	private int times = 0;
	private AnimatedSprite playButton;
	private ArrayList<Line> allDrawLine;
	private TimerHandler timerHandler;

	void createExampleShape() {
		ArrayList<PointF> V = new ArrayList<PointF>();
		V.add(new PointF(140, 150));
		V.add(new PointF(70, 60));
		V.add(new PointF(120, 102));
		V.add(new PointF(120, 220));
		ArrayList<Pair> E = new ArrayList<Pair>();
		E.add(new Pair(0, 1));
		E.add(new Pair(1, 2));
		E.add(new Pair(2, 3));
		E.add(new Pair(3, 0));
		currentShape = new Shape(V, E);
		currentShape.draw(Color.PINK, circleInside, vbom);
	}

	@Override
	public void createScene() {
		init();
		createBackground();
		createHUD();
		createGameOverText();
		createControllers();
		createExampleShape();
		// startMission();
		gameHUD.attachChild(playButton);
		gameHUD.registerTouchArea(playButton);
		setOnSceneTouchListener(this);
	}

	private void init() {
		drawShape = new Shape();
		allDrawLine = new ArrayList<Line>();
		createPhysics();
		smallShape = new Sprite(GameActivity.CAMERA_WIDTH / 2 + 120,
				GameActivity.CAMERA_HEIGHT / 2 + 200,
				resourcesManager.smallShapeRegion, vbom);
		circleInside = new Sprite(GameActivity.CAMERA_WIDTH / 2,
				GameActivity.CAMERA_HEIGHT / 2 + 120,
				resourcesManager.circleInsideRegion, vbom);
		circle = new Sprite(GameActivity.CAMERA_WIDTH / 2,
				GameActivity.CAMERA_HEIGHT / 2 + 120,
				resourcesManager.circleRegion, vbom);
		circle.setScale(((float) GameActivity.CAMERA_HEIGHT / 800) + 0.07f);
		circleInside
				.setScale(((float) GameActivity.CAMERA_HEIGHT / 800) + 0.07f);
		this.attachChild(circle);
		this.attachChild(circleInside);
		timer = new Sprite(GameActivity.CAMERA_WIDTH / 2 - 34,
				GameActivity.CAMERA_HEIGHT / 2 - 115, resourcesManager.vRegion,
				vbom);
		playButton = new AnimatedSprite(GameActivity.CAMERA_WIDTH / 2,
				GameActivity.CAMERA_HEIGHT / 2 + 120,
				resourcesManager.playTiledRegion, vbom) {
			@Override
			public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
					float pTouchAreaLocalX, float pTouchAreaLocalY) {
				resetgame();
				this.setVisible(false);
				gameHUD.unregisterTouchArea(this);
				return super.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX,
						pTouchAreaLocalY);
			}
		};
		final long[] PLAY_ANIMATE = new long[] { 1000, 1000 };

		playButton.animate(PLAY_ANIMATE, 0, 1, true);
		circle.attachChild(timer);
		this.attachChild(smallShape);
		timerHandler = new TimerHandler(0.05f, true, new ITimerCallback() {

			@Override
			public void onTimePassed(TimerHandler pTimerHandler) {
				if (isDrawComplete)
					return;
				if (times > 90) {
					times = 0;
					goc = 0;
					// isDrawComplete = true;
					// GameScene.this.engine.unregisterUpdateHandler(pTimerHandler);
					// circle.detachChildren();
				}
				times++;
				timer.setRotation(goc);
				goc += 4f;
				// v.setScale(((float) GameActivity.CAMERA_HEIGHT / 800) +
				// 0.07f);
			}
		});
	}

	private void resetgame() {

		isDrawComplete = false;
		times = 0;
		goc = 0;

		smallShape.detachChildren();
		smallShape.setPosition(GameActivity.CAMERA_WIDTH / 2 + 120,
				GameActivity.CAMERA_HEIGHT / 2 + 200);

		for (Line line : allDrawLine) {
			backgroundDraw.detachChild(line);
		}
		allDrawLine = new ArrayList<Line>();
		drawShape = new Shape();
		currentPoint = null;
		timerHandler.setTimerSeconds(0.05f);
		this.engine.registerUpdateHandler(timerHandler);
	}

	@Override
	public void onBackKeyPressed() {
		return;
	}

	@Override
	public void disposeScene() {
		camera.setHUD(null);
		camera.setCenter(GameActivity.CAMERA_WIDTH / 2,
				GameActivity.CAMERA_HEIGHT / 2);
		camera.setChaseEntity(this);
	}

	private void addToScore(int i) {
		score += i;
		scoreText.setText("" + score);
		scoreText.setPosition(
				GameActivity.CAMERA_WIDTH / 7 - textScore.length() * 15,
				GameActivity.CAMERA_HEIGHT - 150);
		textScore = score + "";
	}

	private void createBackground() {
		Sprite background = new Sprite(GameActivity.CAMERA_WIDTH / 2,
				GameActivity.CAMERA_HEIGHT / 2,
				resourcesManager.gameBackground, vbom);
		background.setScale(((float) GameActivity.CAMERA_HEIGHT / 800) + 0.07f);
		setBackground(new SpriteBackground(background));

	}

	private void createHUD() {
		gameHUD = new HUD();
		textScore = "0";
		scoreText = new Text(GameActivity.CAMERA_WIDTH / 7 - textScore.length()
				* 15, GameActivity.CAMERA_HEIGHT - 150, resourcesManager.font,
				"0123456789", new TextOptions(HorizontalAlign.LEFT), vbom);
		scoreText.setAnchorCenter(0, 0);
		scoreText.setText("0");
		gameHUD.attachChild(scoreText);

		camera.setHUD(gameHUD);
	}

	private PointF ScaleShape(PointF p) {
		PointF res = new PointF();

		res.x = (float) p.x / 7;
		res.y = (float) p.y / 7;
		// res.x = res.x + 250;
		// res.y = res.y + 420;
		return res;
	}

	
	private void createControllers() {
		backgroundDraw = new Sprite(0, 0, resourcesManager.gameDrawArea, vbom){
			@Override
			public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
					float pTouchAreaLocalX, float pTouchAreaLocalY) {
				if(pSceneTouchEvent.isActionOutside()){
					isDrawComplete = true;
				}
				return super
						.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX, pTouchAreaLocalY);
			}
		};
		backgroundDraw
				.setScale(((float) GameActivity.CAMERA_HEIGHT / 800) + 0.07f);
		backgroundDraw.setPosition(160, 138);
		
		pointList = new ArrayList<Sprite>();
		for (int i = 30; i < 380; i += 80) {
			for (int j = 30; j < 450; j += 80) {
				Sprite point = new Sprite(j, i, resourcesManager.pointRegion,
						vbom) {
					@Override
					public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
							float pTouchAreaLocalX, float pTouchAreaLocalY) {
						if (isDrawComplete)
							return true;

						PointF newPoint = new PointF(this.getX(), this.getY());
						if (currentPoint != newPoint && currentPoint != null) {

							Line line = new Line(currentPoint.x,
									currentPoint.y, newPoint.x, newPoint.y,
									vbom);
							line.setColor(Color.CYAN);

							PointF p1 = ScaleShape(currentPoint);
							PointF p2 = ScaleShape(newPoint);

							int idx2 = drawShape.IndexOfVetex(p2);
							int idx1 = drawShape.IndexOfVetex(p1);
							Pair newEdge;
							if (idx2 == -1) {
								drawShape.Vertex.add(p2);
								newEdge = new Pair(idx1,
										drawShape.Vertex.size() - 1);
							} else {
								newEdge = new Pair(idx1, idx2);
							}
							Line linesmall = new Line(p1.x, p1.y, p2.x, p2.y,
									vbom);
							if (drawShape.containsEdge(newEdge)) {
								// isDrawComplete = true;
								linesmall.setColor(Color.RED);
								line.setColor(Color.RED);
							} else {
								drawShape.Edge.add(newEdge);
							}

							smallShape.attachChild(linesmall);
							backgroundDraw.attachChild(line);
							allDrawLine.add(line);
						}
						currentPoint = newPoint;
						if (isDrawComplete || pSceneTouchEvent.isActionUp()
								|| pSceneTouchEvent.isActionOutside()) {
							smallShape.registerEntityModifier(new MoveModifier(
									0.3f, smallShape.getX(), smallShape.getY(),
									smallShape.getX(),
									GameActivity.CAMERA_HEIGHT / 2 + 70));
							playButton.setVisible(true);
							isDrawComplete = true;
							gameHUD.registerTouchArea(playButton);
							this.unregisterUpdateHandler(timerHandler);
						}
						return super.onAreaTouched(pSceneTouchEvent,
								pTouchAreaLocalX, pTouchAreaLocalY);
					}
				};

				pointList.add(point);
				backgroundDraw.attachChild(point);
				gameHUD.registerTouchArea(point);
			}
		}

		gameHUD.setTouchAreaBindingOnActionMoveEnabled(true);
		gameHUD.setTouchAreaBindingOnActionDownEnabled(true);
		this.setTouchAreaBindingOnActionMoveEnabled(true);
		this.setTouchAreaBindingOnActionDownEnabled(true);
		gameHUD.attachChild(backgroundDraw);
		gameHUD.registerTouchArea(backgroundDraw);
	}

	private void createPhysics() {
		physicsWorld = new FixedStepPhysicsWorld(60, new Vector2(0, -17), false);
		physicsWorld.setContactListener(contactListener());
		registerUpdateHandler(physicsWorld);
	}

	@Override
	public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
		return false;
	}

	private void createGameOverText() {
		gameOverText = new Text(0, 0, resourcesManager.font, "Game Over!", vbom);
	}

	private ContactListener contactListener() {
		ContactListener contactListener = new ContactListener() {

			@Override
			public void preSolve(Contact contact, Manifold oldManifold) {
				// TODO Auto-generated method stub

			}

			@Override
			public void postSolve(Contact contact, ContactImpulse impulse) {
				// TODO Auto-generated method stub

			}

			@Override
			public void endContact(Contact contact) {
				final Fixture x1 = contact.getFixtureA();
				final Fixture x2 = contact.getFixtureB();

				if (x1.getBody().getUserData() != null
						&& x2.getBody().getUserData() != null) {
					if (x2.getBody().getUserData().equals("player")) {

					}
				}
			}

			@Override
			public void beginContact(Contact contact) {
				final Fixture x1 = contact.getFixtureA();
				final Fixture x2 = contact.getFixtureB();
				if (x1.getBody().getUserData() != null
						&& x2.getBody().getUserData() != null) {
					if (x2.getBody().getUserData().equals("player")) {

					}
					if (x1.getBody().getUserData().equals("platform3")
							&& x2.getBody().getUserData().equals("player")) {
						x1.getBody().setType(BodyType.DynamicBody);
					}
					if (x1.getBody().getUserData().equals("platform2")
							&& x2.getBody().getUserData().equals("player")) {
						engine.registerUpdateHandler(new TimerHandler(0.2f,
								new ITimerCallback() {

									@Override
									public void onTimePassed(
											TimerHandler pTimerHandler) {
										pTimerHandler.reset();
										engine.unregisterUpdateHandler(pTimerHandler);
										x1.getBody().setType(
												BodyType.DynamicBody);
									}
								}));
					}

				}
			}
		};
		return contactListener;
	}

	@Override
	public SceneType getSceneType() {
		return SceneType.SCENE_GAME;
	}

}
